package com.wwdx.controller.base;

import com.google.gson.JsonObject;
import com.wwdx.model.WwdxOpenAuthModel;
import com.wwdx.service.impl.BaseWxOpenService;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.URIUtil;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import me.chanjar.weixin.open.api.WxOpenComponentService;
import me.chanjar.weixin.open.bean.auth.WxOpenAuthorizationInfo;
import me.chanjar.weixin.open.bean.auth.WxOpenAuthorizerInfo;
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerInfoResult;
import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

/**
 * @author liguoliang
 * @date 2018/9/30 23:02
 */
public abstract class BaseOpenAuthController extends BaseController{

    /**
     * 获取子类service
     * @return BaseWxOpenService
     */
    protected abstract BaseWxOpenService getWxOpenService();

    /**
     * 返回回调地址前缀
     * @return str
     */
    protected abstract String getPreUrl();

    /**
     * 移动端授权
     */
    @RequestMapping("/goto_auth_url/h5")
    @ApiOperation(value = "移动端授权",httpMethod = "GET")
    @ApiImplicitParam(value = "微信openId",name = "openId",required = true)
    public void gotoH5PreAuthUrl(String openId,HttpServletResponse response) throws IOException{
        String url = domain + this.getPreUrl() +"/jump?openId="+openId;
        String api = "https://mp.weixin.qq.com/safe/bindcomponent?action=bindcomponent&auth_type=3&no_scan=1&component_appid=%s&pre_auth_code=%s&redirect_uri=%s#wechat_redirect";
        String componentAccessToken = this.getWxOpenService().getWxOpenConfigStorage().getComponentAccessToken();
        String componentAppId = this.getWxOpenService().getWxOpenConfigStorage().getComponentAppId();
        try {
            if (StringUtils.isBlank(componentAccessToken)){
                componentAccessToken = this.getWxOpenService().getWxOpenComponentService().getComponentAccessToken(true);
            }
            JsonObject jsonObject = new JsonObject();
            jsonObject.addProperty("component_appid", componentAppId);
            String preAuthcodeUrl = WxOpenComponentService.API_CREATE_PREAUTHCODE_URL+"?component_access_token="+componentAccessToken;
            String responseContent = this.getWxOpenService().post(preAuthcodeUrl, jsonObject.toString());
            jsonObject = WxGsonBuilder.create().fromJson(responseContent, JsonObject.class);
            url = String.format(api, componentAppId, jsonObject.get("pre_auth_code").getAsString(), URIUtil.encodeURIComponent(url));
            //h5授权页
            response.sendRedirect(url);
        }catch (WxErrorException e){
            logger.error(e.getMessage());
        }
    }

    /**
     * PC端授权
     */
    @RequestMapping("/goto_auth_url/pc")
    @ApiOperation(value = "PC端授权",httpMethod = "GET")
    @ApiImplicitParam(value = "微信openId",name = "openId",required = true)
    public void gotoPCPreAuthUrl(String openId,HttpServletResponse response) throws IOException{
        String url = domain + this.getPreUrl() +"/jump?openId="+openId;
        try {
            response.sendRedirect(this.getWxOpenService().getWxOpenComponentService().getPreAuthUrl(url));
        } catch (WxErrorException e) {
            logger.error(e.getMessage());
        }
    }

    @RequestMapping("/jump")
    @ApiIgnore
    public void jump(String openId, @RequestParam("auth_code") String authorizationCode , HttpServletResponse response) throws IOException {
        try {
            WxOpenComponentService wxOpenComponentService = this.getWxOpenService().getWxOpenComponentService();
            WxOpenQueryAuthResult queryAuthResult = wxOpenComponentService.getQueryAuth(authorizationCode);
            String authorizerAppid = queryAuthResult.getAuthorizationInfo().getAuthorizerAppid();
            WxOpenAuthorizerInfoResult authorizerInfoResult = wxOpenComponentService.getAuthorizerInfo(authorizerAppid);
            WxOpenAuthorizationInfo authorizationInfo = authorizerInfoResult.getAuthorizationInfo();
            WxOpenAuthorizerInfo authorizerInfo = authorizerInfoResult.getAuthorizerInfo();
            Integer serviceTypeInfo = authorizerInfo.getServiceTypeInfo();
            //授权方公众号类型，0代表订阅号，1代表由历史老帐号升级后的订阅号，2代表服务号
            switch (serviceTypeInfo){
                case 2:
                    WwdxOpenAuthModel wwdxOpenAuthModel = wwdxOpenAuthService.getByAppId(authorizerAppid);
                    if (wwdxOpenAuthModel == null){
                        wwdxOpenAuthModel = new WwdxOpenAuthModel();
                        BeanUtils.copyProperties(authorizerInfo,wwdxOpenAuthModel);
                        wwdxOpenAuthModel.setAuthorizerAppid(authorizerAppid);
                        wwdxOpenAuthModel.setFuncInfo(authorizationInfo.getFuncInfo().toString());
                        wwdxOpenAuthModel.setOpenId(openId);
                        wwdxOpenAuthModel.setStatus(1);
                        wwdxOpenAuthService.save(wwdxOpenAuthModel);
                    }else {
                        wwdxOpenAuthModel.setStatus(1);
                        wwdxOpenAuthService.update(wwdxOpenAuthModel);
                    }
                    break;
                default:
                    response.sendRedirect(wechatUrl + "unservice.html?msg=" + resultData("非服务号"));
                    return;
            }
            response.sendRedirect(wechatUrl + "service.html?merchantId=" + openId);
        } catch (WxErrorException e) {
            logger.error(e.getMessage());
            response.sendRedirect(wechatUrl + "unservice.html?msg=" + resultData(e.getMessage()));
        }
    }

    private String resultData(String data){
        if (data != null){
            try {
                return URLEncoder.encode(data,"utf-8");
            }catch (UnsupportedEncodingException e){
                logger.error(e.getMessage());
            }
        }
        return null;
    }
}